<?php
namespace control;

/*
*半成品加工单类
*/

class semiMachiningOrderClass extends adIndexClass
{
    private const page = 'semiMachiningOrder';
    private const table = 'machining_order';
    private const tableMx = 'machining_order_detail';
    private const table_material = 'machining_order_mx';
    private const title = '半成品加工单';
    private array $stateOption = ['草稿', '待确认', '已确认'];

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            case 'qualityTrackSearch':
                $tr = [
                    'type'          => [
                        'name'  => "质检类型",
                        'width' => 150,
                    ],
                    'recordDate' => [
                        'name'  => "单据日期",
                        'width' => 150,
                    ],
                    'orderNo'  => [
                        'name'  => "单据编号",
                        'width' => 150,
                    ],
                    'lineName'  => [
                        'name'  => '生产线',
                        'width' => 100,
                    ],
                    'processName'  => [
                        'name'  => '工序',
                        'width' => 100,
                    ],
                    'code'  => [
                        'name'  => '物料编码',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'name'         => [
                        'name'  => '物料名称',
                        'width' => 150,
                    ],
                    'model'          => [
                        'name'  => '规格型号',
                        'width' => 150,
                    ],
                    'unit'          => [
                        'name'  => '单位',
                        'width' => 60,
                    ],
                    'batch'          => [
                        'name'  => '生产批次',
                        'width' => 100,
                        'sort' => 1,
                    ],
                    'num'          => [
                        'name'  => '完工数量',
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'passNum'          => [
                        'name'  => '合格数量',
                        'width' => 100,
                        'sort' => 1,
                    ],
                    'badNum'          => [
                        'name'  => '不良数量',
                        'width' => 100,
                    ],
                    'state'          => [
                        'name'  => '状态',
                        'width' => 150,
                    ],
                    'checkTime'          => [
                        'name'  => '质检日期',
                        'width' => 120,
                        'sort' => 1,
                    ]
                ];
                break;
            default:
                $tr = [
                    'orderNo'          => [
                        'name'  => "单据编号",
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'tag' => [
                        'name'  => "单据标签",
                        'width' => 150,
                    ],
                    'line'  => [
                        'name'  => "生产线",
                        'width' => 200,
                    ],
                    'subject'  => [
                        'name'  => '存货类型',
                        'width' => 100,
                    ],
                    'code'  => [
                        'name'  => '物料编码',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'materialName'         => [
                        'name'  => '物料名称',
                        'width' => 150,
                    ],
                    'model'          => [
                        'name'  => '规格型号',
                        'width' => 150,
                    ],
                    'unit'          => [
                        'name'  => '单位',
                        'width' => 60,
                    ],
                    'num'          => [
                        'name'  => '生产数量',
                        'width' => 100,
                        'sort' => 1,
                    ],
                    'inStockNum'          => [
                        'name'  => '已生产入库数量',
                        'width' => 120,
                    ],
                    'notInNum'          => [
                        'name'  => '未入库数量',
                        'width' => 100,
                    ],
                    'completionRate'          => [
                        'name'  => '生产完成率',
                        'width' => 120,
                    ],
                    'relativeNo'          => [
                        'name'  => '关联生产计划单',
                        'width' => 150,
                    ],
                    'startDate'          => [
                        'name'  => '计划开工时间',
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'endDate'          => [
                        'name'  => '计划完工时间',
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'recordDate'          => [
                        'name'  => '单据日期',
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'state'          => [
                        'name'  => '状态',
                        'width' => 100,

                    ]
                ];
        }
        return $tr;
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    "单据编号" => text(array("name" => "orderNo")),
                    "标签"   => text(array("name" => "tags")),
                    "物料编码"   => text(array("name" => "code")),
                ],
                [
                    "物料名称"   => text(array("name" => "materialName")),
                    '生产线'  => selectMultiple(["name" => "lineId", 'table' => "product_line", 'sqlId' => 'id', 'where' => "coid = '" . self::$coid . "'", 'sqlField' => 'name', 'class' => 'width200']),
                    "计划开工时间" => text(array("name" => "startTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                ],
                [
                    '计划完工时间' => text(array("name" => "endTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                    '状态' => select(["name" => "state", 'option' => $this->stateOption]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /*列表-查询条件*/
    public function home()
    {
        $html = $this->homeOptions(false);
        //控件
        $button = "";
        $url = root . "control/adIndex.html?cla=" . self::page;
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"newIframe('" . self::title . "详情','" . $url . "&fun=edit')\" class='spanButton'>新增</span>\n
                        <span onclick=\"layer('orderTag','batchAddTags',{'table':'".self::table."','title':'".self::title."'})\" class='spanButton'>批量打标签</span>\n";
            $button .= "<span class='spanButton' onclick=\"layer('{$this->get('cla')}', 'operate', {'act': 'close'})\">批量关闭</span>\n";
        }
        if ($this->power(self::page, "del")) {
            $button .= "<span class='spanButton' onclick=\"layer('{$this->get('cla')}', 'operate', {'act': 'batchDel'})\">删除</span>\n";
        }
        if ($this->power(self::page, "print")) {
            $button .= " <span onclick=\"batchPrint('" . $this->get('cla') . "')\" class='spanButton'>批量打印</span>\n";
        }
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /*客户列表-查询结果*/
    public function homeSearch()
    {
        //like查询数组
        $like = array(
            "a.orderNo" => $this->post('orderNo'),
            "b.name" => $this->post('materialName'),
            "b.code" => $this->post('code'),
        );
        //全等查询数组
        $equal = array(
            "a.state" => $this->post('state'),
            "a.lineId" => $this->post('lineId'),
            'a.coid' => self::$coid,
            'a.orderType'=>'半成品'
        );
        $and = '';
        if ($this->post('createTime')) {
            $and .= self::timeComparison($this->post('createTime'), field: 'a.recordDate');
        }
        if ($this->post('tages')){
            $and.=" and (";
            $tagsArr = explode('，',$this->post('tages'));
            foreach ($tagsArr as $index=>$tag){
                $and.=$index==0?"a.tags like '%".$tag."%'":" and a.tags like '%".$tag."%'";
            }
            $and.=")";
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'a.recordDate desc,a.orderNo',
            "sort" => $this->post('list_sort') ?: "asc",
            "array"   => array(),
        ));
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $and;
        $page = $this->page(array(
            "table" => self::table . " as a left join " . self::table_material . ' as c on c.orderId = a.id left join material as b on c.materialId = b.id ',
            'field' => "c.*,b.subject,b.name as materialName,b.code,b.model,a.state,a.lineId,a.orderNo,a.isClose,a.startDate,a.endDate,a.recordDate,a.id as orderId",
            "where" => $where,
            "order" => $orderBy['orderBy']
        ));
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        //获取记录
        $url = root . "control/adIndex.html?cla=" . self::page;
        $machiningObj = new machiningOrderClass();
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                "box" => array("name" => "listId", "value" => $array['id']?:$array['orderId']),
                "edit" => array("title" => "编辑", "click" => "newIframe('" . self::title . "详情','" . $url . "&fun=edit&id=" . $array['orderId'] . "')"),
                "detail" => array("title" => self::title . "详情", "click" => "newIframe('" . self::title . "详情','" . $url . "&fun=detail&id=" . $array['orderId'] . "')"),
                'print' => array('title' => '打印', 'click' => "window.open('" . root . "control/adIndex.html?cla=" . self::page . "&fun=printPage&id={$array['orderId']}')"),
                'track'=> array("title" => "单据追踪", "click" => "newIframe('单据追踪','" . root . "control/adIndex.html?cla=orderTrack&fun=home&orderType=半成品加工单&id=" . $array['orderId'] . "')"),
            );
            if ($array['state'] == '已确认') {
                unset($dominate['edit']);
            }
            //已生产入库的数量
            $inStockNum = $machiningObj->inStockNum($array['id'],$array['unit']);
            $closeSign = $array['isClose'] ? "<span class='no-choose'></span>" : '';//关闭单据颜色显示标志
            $liButton[] = $this->dominate($dominate) . $closeSign;
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'tag':
                        $tag = orderTagClass::getTagName($array['orderId']);
                        $row[] = $tag;
                        break;
                    case 'line':
                        $line = query('product_line', "id = '$array[lineId]'");
                        $row[] = $line['workshop'].'-'.$line['name'];
                        break;
                    case 'num':
                        $row[] = self::lostZero($array['num'],'numPrecision');
                        break;
                    case 'inStockNum':
                        $row[] = self::lostZero($inStockNum, 'numPrecision');
                        break;
                    case 'notInNum':
                        $row[] = self::lostZero($array['num']-$inStockNum,'numPrecision');
                        break;
                    case 'completionRate':
                        $row[] = $machiningObj->formatRatio($inStockNum,$array['num']);
                        break;
                    case 'relativeNo':
                        $semi_demands = query('semi_demands', "id = '$array[sourceId]'");
                        $machining_order = query('machining_order', "id = '$semi_demands[sourceId]'");
                        $row[] = $machining_order['orderNo'];
                        break;
                    case 'startDate':
                    case 'endDate':
                        $row[] = self::null($array[$key]);
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        $totalQuery = find([
            'table'  => self::table . " as a left join " . self::table_material . ' as c on c.orderId = a.id left join material as b on c.materialId = b.id ',
            'single' => $where,
            'field'  => "ifnull(sum(c.num),0) as num",
        ]);
        // 生产入库数量
        // 单位转换 先将inventory_detail的数量转为主单位数量(CASE WHEN mx.unit = b.unit_one THEN mx.num*b.unit_one_num WHEN mx.unit = b.unit_two THEN mx.num*b.unit_two_num ELSE mx.num END)
        // 再将主单位数量转为machining_order_mx的单位数量（主单位数量/machining_order_mx的单位转换数量）
        $inventory = find(array(
            'table'  => self::table . " as a left join " . self::table_material . ' as c on c.orderId = a.id left join material as b on c.materialId = b.id join machining_in_order_detail as miod on miod.sourceId = c.id join inventory_detail as mx on mx.sourceId = miod.id ',
            'single'=>$where,
            'field'=>"ifnull(SUM((CASE WHEN mx.unit = b.unit_one THEN mx.num*b.unit_one_num WHEN mx.unit = b.unit_two THEN mx.num*b.unit_two_num ELSE mx.num END)/(CASE WHEN c.unit = b.unit_one THEN b.unit_one_num WHEN c.unit = b.unit_two THEN b.unit_two_num ELSE 1 END)),0) AS num"
        ));
        $total    = [
            'num'        => self::lostZero($totalQuery['num'], 'numPrecision'),
            'inStockNum'        => self::lostZero($inventory['num'], 'numPrecision'),
            'notInNum' => self::formattingFigure($totalQuery['num'] - $inventory['num'], 'numPrecision'),
        ];
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
            "total"       => $total,
        ));
        //返回
        $json['html'] = $page['hint'] . "<form name='listForm'>" . $li . "</form>" .  machiningOrderClass::closeJs() .$page['button'] . clear;
        return json_encode($json, 320);
    }
    /**
     * 列表删除
     */
    public function batchDel(): bool|string
    {
        $listId = $this->post('listId');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = "你没有删除" . self::title . "的权限";
        } elseif (empty($listId) || !is_array($listId)) {
            $json['warn'] = '您还没有选择单据';
        } else {
            $x = 0;
            $text = '';
            $all = find(array(
                'table' => 'machining_order_mx',
                'field' => "distinct orderId",
                "where" => "coid = '" . self::$coid . "' and id in ('" . implode("','", $listId) . "')"
            ));
            //草稿状态下的半成品加工单，未完善产品明细
            $order  = find(array(
                'table' => 'machining_order',
                'field' => "id as orderId",
                "where" => "coid = '" . self::$coid . "' and state = '草稿' and id in ('" . implode("','", $listId) . "')"
            ));
            $all = array_merge($all,$order);
            foreach ($all['array'] as $array) {
                $machiningOrder = query(self::table, "id = '$array[orderId]'");
                if ($machiningOrder['state'] == '已确认') {
                    $warn = "删除失败：已确认，暂不能删除";
                } else {
                    //最后删除基本参数
                    delete(array("table" => self::table, "where" => " id = '$array[orderId]' "));
                    delete(array("table" => self::tableMx, "where" => " orderId = '$array[orderId]' "));
                    delete(array("table" => self::table_material, "where" => " orderId = '$array[orderId]' "));
                    delete(array("table" => "auditing_follow", "where" => " typeId = '$array[orderId]' "));
                    //返回
                    $warn = "删除成功";
                    $x++;
                }
                $text .= self::title . "ID【" . $machiningOrder['id'] . "】,单号【{$machiningOrder['orderNo']}】" . $warn . "。<br>";
            }
            $text = $this->control['name'] . "删除了" . self::title . "，结果如下：<br>" . $text;
            $this->logText(["type" => self::page, "text" => $text]);
            $json['warn'] = 2;
            $json['msg'] = "删除了" . $x . "个" . self::title . "，详情见系统日志。";
        }
        return json_encode($json, 320);
    }

    /**
     * 批量添加标签编辑
     */
    public function closeEdit(): bool|string
    {
        $listId = $this->post('listId');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (empty($listId) || !is_array($listId)) {
            $json['warn'] = '您还没有选择单据';
        } else {
            $x = 0;
            $text = '';
            $all = find(array(
                'table' => 'machining_order_mx',
                'field' => "distinct orderId",
                "where" => "coid = '" . self::$coid . "' and id in ('" . implode("','", $listId) . "')"
            ));
            foreach ($all['array'] as $array) {
                $machiningOrder = query(self::table, "id = '$array[orderId]'");
                if ($machiningOrder['state'] =='已确认' && !$machiningOrder['isClose']) {
                    $warn = update(array(
                        'table' => self::table,
                        'field' => [
                            'isClose' => 1
                        ],
                        'where' => "id = '$machiningOrder[id]'"
                    ));
                    if ($warn == '更新成功') {
                        $x++;
//                        materialDistributeClass::avgInventoryPrice($machiningOrder['id']);
                        self::insertOperateLog($machiningOrder['id'],self::title,"关闭");
                        $text .= "半成品加工单【{$machiningOrder['orderNo']}】,ID：【{$machiningOrder['id']}】关闭成功<br>";
                    } else {
                        $text .= "半成品加工单【{$machiningOrder['orderNo']}】,ID：【{$machiningOrder['id']}】关闭失败<br>";
                    }
                }
            }
            $this->logText(["type" => self::page, "text" => $this->control['name'] . "批量关闭半成品加工单如下：" . $text]);
            $json['warn'] = 2;
            $_SESSION['warn'] = '成功关闭了' . $x . '个半成品加工单';

        }
        return json_encode($json, 320);
    }

    /**
     * 编辑页
     *
     * @return string
     */
    public function edit(): string
    {
        $id = $this->get('id')?:suiji();
        $info = query(self::table, " id = '" . $id . "' ");
        $machiningObj = new machiningOrderClass();
        $button[] = [
            "name" => "保存为草稿",
            "type" => "点击事件",
            "title" => "保存",
            'fun' => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&fun=editEdit')",
        ];
        $button[] = [
            'style' => 'li-btn-blue-bg',
            "name" => "保存并提交",
            "type" => "点击事件",
            "title" => "保存",
            'fun' => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&fun=saveAndCommit')"
        ];
        $tr[] = ['', '源单编号', '产品名称', '物料编码', '物料名称', '规格型号', '单位', '额定数量', '损耗率%', '预计用量', '当前可用库存', '备注'];
        $result = find(array('table' => self::tableMx, 'where' => "orderId = '$info[id]' order by list"));
        foreach ($result['array'] as $k=>$array) {
            $material = query('material', " id = '$array[materialId]'");
            $unitOption = machiningOrderClass::unitOption($material['id']);
            $machiningOrderMx = query(self::table_material, " id = '$array[targetSkuId]'");
            $productDemand = query('semi_demands',"id = '$machiningOrderMx[sourceId]'");
            $machining_order = query('machining_order', "id = '$productDemand[sourceId]'");
            $tr[] = [
                componentClass::tablePperation($k+1,"delTableRow(this)").
                hidden(array('name' => 'mxId[]', 'value' => $array['id'])) .
                hidden(array('name' => 'targetSkuId[]', 'value' => $array['targetSkuId'])) .
                hidden(array('name' => 'materialId[]', 'value' => $array['materialId'])),
                $machining_order['orderNo'],
                materialClass::getName($machiningOrderMx['materialId'],short: true),
                $material['code'],
                $material['name'],
                $material['model'],
                select(array('name' => 'unitDetail[]', 'data' => ['unit' => $array['unit']], 'change' => 'unitChange', 'option' => $unitOption, 'title' => '单位', 'value' => $array['unit'])),
                text(array('name' => 'mxNum[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100','blur' => 'countNum', 'value' => self::lostZero($array['num'],'numPrecision'))),
                text(array('name' => 'loss[]', 'other' => self::digitalFiltering('lossRate'),'class'=>'text width100','blur' => 'countNum', 'value' => $array['loss'] * 100)),
                "<span class='totalNum'>".self::lostZero($array['quantity'],'numPrecision')."</span>",
                "<span class='inventory'>" . machiningOrderClass::inventory($array['materialId'], $array['unit']) . "</span>",
                text(array('name' => 'mxText[]', 'class' => 'text textPrice', 'value' => $array['text'])),
            ];
        }
        $list = $this->listTable(array('tr' => $tr, 'end' => true));
        $obtainBomBtn =<<<eof
<span class="smallButton" onclick="obtainBom()">从BOM获取</span>&emsp;
<span onclick="newIframe('BOM表',root+'control/adIndex.html?cla=bom&fun=edit','供应链','资料')" class="smallButton">新建BOM</span>
eof;
        if (optionSettingClass::getSettingItem('生产','withOutBom')){
            $obtainBomBtn='';
        }
        $tableBut = <<<efo
                <span class="smallButton" onclick="layer('{$this->get('cla')}','addMx',$('form[name=semiMachiningOrderEditForm]').serialize())">选择物料</span>
                $obtainBomBtn
efo;
        $table = <<<efo
                <div id="material-table-content">{$list}</div>
efo;

        $materialTr[] = ['', '生产计划单', '产品编码', '产品名称', '规格型号', '单位', '计划数量', '生产批次','BOM版本', '工艺路线', '备注'];
        if ($this->get('source') == 'semiProductDemand') {
            //从半成品需求来
            $listIdArr = explode(',', $this->get('listId'));
            foreach ($listIdArr as $k=>$demandId) {
                $productDemand = query('semi_demands',"id = '$demandId'");
                $machining_order = query('machining_order', "id = '$productDemand[sourceId]'");
                $material = query('material', " id = '$productDemand[materialId]'");
                $unitOption = machiningOrderClass::unitOption($material['id']);
                //默认bom
                $detaultBom = query('bom', "materialId = '$material[id]' and state = '启用' and isDefault = 1");
                //默认工艺路线
                $routingId = $machiningObj->defaultRouting($material['id']);
                $detaultRouting = query('routing', "id = '$routingId'");
                $allTypeId = machiningInOrderClass::getAllParentTypeId($material['typeId']);
                //已进入半成品加工单的数量
                $productNum = 0;
                $result = find(array('table' => 'machining_order_mx', 'where' => "sourceId = '$productDemand[id]'"));
                foreach ($result['array'] as $value) {
                    $productNum += machiningOrderClass::material_num_change($value['materialId'], $value['unit'], $material['unit'], $value['num']);
                }
                $materialTr[] = [
                    componentClass::tablePperation($k+1,"delTableRow(this)").
                    hidden(array('name' => 'productId[]', 'value' => self::getId())) .
                    hidden(array('name' => 'sourceId[]', 'value' => $productDemand['id'])) .
                    hidden(array('name' => 'skuId[]', 'value' => $productDemand['materialId'])),
                    $machining_order['orderNo'] ?: '-',
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    select(array('name' => 'unit[]', 'data' => ['unit' => $material['unit']], 'change' => 'unitChangeProduct', 'option' => $unitOption, 'title' => '单位', 'value' => $material['unit'])),
                    text(array('name' => 'num[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100', 'value' => self::lostZero($productDemand['num'] - $productNum,'numPrecision'))),
                    text(array('name' => 'batch[]', 'class' => 'width100')),
                    selectMultiple(array('name' => 'bomId[]', 'class' => 'width200', 'title' => 'BOM版本', 'table' => 'bom', 'where' => "bomType like '%生产%' and state = '启用' and coid = '" . self::$coid . "' and materialId = '$material[id]' order by time desc", 'sqlId' => 'id', 'sqlField' => 'bomVersion', 'value' => $detaultBom['id'])),
                    selectMultiple(array('name' => 'routingId[]', 'class' => 'width200', 'title' => '工艺路线', 'option' => $machiningObj->routingOption($material['id'], $allTypeId),'value' => $detaultRouting['id'])),
                    text(array('name' => 'materialText[]','value'=>$machining_order['text'], 'class' => 'width100')),
                ];
            }
        } else {
            $result = find(array('table' => self::table_material, 'where' => "orderId = '$info[id]' order by list"));
            foreach ($result['array'] as $k=>$array) {
                $relativeNo = '-';
                if ($array['sourceTable'] == 'semi_demands') {
                    $productDemand = query('semi_demands',"id = '$array[sourceId]'");
                    $machiningOrder = query('machining_order', "id = '$productDemand[sourceId]'");
                    $relativeNo = $machiningOrder['orderNo'];
                }
                $material = query('material', " id = '$array[materialId]'");
                $unitOption = machiningOrderClass::unitOption($material['id']);
                $allTypeId = machiningInOrderClass::getAllParentTypeId($material['typeId']);
                $materialTr[] = [
                    componentClass::tablePperation($k+1,"delTableRow(this)").
                    hidden(array('name' => 'productId[]', 'value' => $array['id'])) .
                    hidden(array('name' => 'sourceId[]', 'value' => $array['sourceId'])) .
                    hidden(array('name' => 'skuId[]', 'value' => $array['materialId'])),
                    $relativeNo,
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    select(array('name' => 'unit[]', 'data' => ['unit' => $array['unit']], 'change' => 'unitChangeProduct', 'option' => $unitOption, 'title' => '单位', 'value' => $array['unit'])),
                    text(array('name' => 'num[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100', 'value' => self::lostZero($array['num'],'numPrecision'))),
                    text(array('name' => 'batch[]', 'class' => 'width100','value' =>$array['batch'])),
                    selectMultiple(array('name' => 'bomId[]', 'class' => 'width200', 'title' => 'BOM版本', 'table' => 'bom', 'where' => "bomType like '%生产%' and state = '启用' and coid = '" . self::$coid . "' and materialId = '$array[materialId]' order by time desc", 'sqlId' => 'id', 'sqlField' => 'bomVersion', 'value' => $array['bomId'])),
                    selectMultiple(array('name' => 'routingId[]', 'class' => 'width200', 'title' => '工艺路线', 'option' => $machiningObj->routingOption($material['id'], $allTypeId),'value' => $array['routingId'])),
                    text(array('name' => 'materialText[]', 'class' => 'width100', 'value' => $array['text'])),
                ];
            }
        }

        $materialMx = $this->listTable(array('tr' => $materialTr, 'end' => true));
        $materialMxBut = <<<efo
                <span class="smallButton" onclick="layer('{$this->get('cla')}','addMaterial',$('form[name=semiMachiningOrderEditForm]').serialize())">选择物料</span>
efo;

        $line = query('product_line', "id = '$info[lineId]'");

        //表单
        $data['button'] = $this->tableShowButton($button);
        $body = $this->edit4([
            '基本信息' => [
                [
                    must . "单据日期：" => text(["name" => "recordDate", 'laydate' => [], "value" => $info['recordDate'] ?: $this->date]),
                    must . "生产线：" => repeatSelect(array(
                            'name' => 'workshop',
                            'title' => '生产车间',
                            'class' => 'width100',
                            'change' => "getLine",
                            'sqlForm' => "product_line where coid = '" . self::$coid . "' and state = '启用'",
                            'sqlField' => 'workshop',
                            'value' => $line['workshop']
                        )) .
                        idSelect(array(
                            'name' => 'lineId',
                            'sqlForm' => "product_line where coid = '" . self::$coid . "' and state = '启用' and workshop = '$line[workshop]'",
                            'sqlId' => 'id',
                            'sqlField' => 'name',
                            'title' => '生产线',
                            'class' => 'width100',
                            'value' => $info['lineId']
                        )),
                    must . "计划开工时间：" => text(["name" => "startDate", 'laydate' => [], "value" => $info['startDate']]),
                    must . "计划完工时间：" => text(["name" => "endDate", 'laydate' => [], "value" => $info['endDate']]),
                ],
                [
                    "备注：" => textarea(["name" => "text", 'class' => 'long', "value" => $info['text']]),
                ],
            ]
        ]);
        $body .= $this->editList([
            'id' => 'materialMx',
            'title' => '产品明细',
            'button' => $materialMxBut,
            'html' => $materialMx,
        ]);
        $body .= $this->editList([
            'id' => 'materialTable',
            'title' => '所需物料',
            'button' => $tableBut,
            'html' => $table,
        ]);
        $data['html'] = $this->pageEdit([
            "html" => $body,
            'hidden' => hidden(['name' => 'id', 'value' => $id]) . hidden(array('name' => 'qualityId', 'value' => $this->get('linkId'))),
        ]);
        $data['html'] .= <<<efo
<script>
//根据单位转换所需数量和库存
function unitChange(e){
    let unit = e.value;
    if (!unit){
        msg('请选择单位')
        return '';
    }
    let oldUnit = $(e).data('unit');
    $(e).data('unit',unit);
    let loss = $(e).parent().parent().find("[name='loss[]']").val();
    let num = $(e).parent().parent().find("[name='mxNum[]']").val();
    let id = $(e).parent().parent().find("[name='materialId[]']").val();
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=unitChange',{unit:unit,oldUnit:oldUnit,num:num,loss:loss,id:id},function(res) {
        if (res.warn===2){
            $(e).parent().parent().find("[name='mxNum[]']").val(res.num);
            $(e).parent().parent().find(".totalNum").html(res.totalNum);
            $(e).parent().parent().find(".inventory").html(res.inventoryNum);
        }else{
            msg(res.warn);
        }
    },'json');
}
function unitChangeProduct(e){
    let unit = e.value;
    if (!unit){
        msg('请选择单位')
        return '';
    }
    let oldUnit = $(e).data('unit');
    $(e).data('unit',unit);
    let num = $(e).parent().parent().find("[name='num[]']").val();
    let id = $(e).parent().parent().find("[name='skuId[]']").val();
    $.post(root+'control/adIndex.html?cla=machiningOrder&fun=unitChange',{unit:unit,oldUnit:oldUnit,num:num,id:id},function(res) {
        if (res.warn===2){
            $(e).parent().parent().find("[name='num[]']").val(res.num);
        }else{
            msg(res.warn);
        }
    },'json');
}
//根据BOM计算物料使用量
function obtainBom(){
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=obtainBom',$('form[name=semiMachiningOrderEditForm]').serialize(),function(res) {
        if (res.warn ==2){
            $("#material-table-content").empty().append(res.html);
            resetNumber($("#material-table-content"))
        }else{
            msg(res.warn);
        }
    },'json');
}
//计算预定数量
function countNum(e){
    let loss = $(e).parent().parent().find("[name='loss[]']").val();
    let num = $(e).parent().parent().find("[name='mxNum[]']").val();
    $(e).parent().parent().find(".totalNum").html((Number(num)*(1+Number(loss)/100)).toFixed(publicSettings.numPrecision.num))
}
//获取生产线
function getLine(e){
     let val = e.value;
     $.post(root+'control/adIndex.html?cla=machiningOrder&fun=getLine',{val:val},function(res) {
             $("select[name='lineId']").html(res.html);
        },'json');
}
//选择物料
function addRow(){
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addMxEdit',$("form[name='mxForm']").serialize(),function(res) {
        $('#semiMachiningOrderAddMx').hide();
        $("#materialTable tbody").append(res.html);
        resetNumber($("#materialTable"))
    },'json');
}
//选择生产产品
function addMaterial(classify = ''){
    if (classify ==='saleOrder'){
         $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addOrderEdit',$("form[name='saleOrderForm']").serialize(),function(res) {
         if (res.warn ==2){
            $('#semiMachiningOrderAddOrder').hide();
            $("#materialMx tbody").append(res.html);
            resetNumber($("#materialMx"))
         }else{
             msg(res.warn);
         }
        },'json');
    }else if(classify ==='saleRefundOrder'){
        $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addRefundOrderEdit',$("form[name='saleRefundOrderForm']").serialize(),function(res) {
         if (res.warn ==2){
            $('#semiMachiningOrderAddRefundOrder').hide()
           $("#materialMx tbody").append(res.html);
           resetNumber($("#materialMx"))
         }else{
             msg(res.warn);
         }
        },'json');
    }else{
         $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addMaterialEdit',$("form[name='materialMxForm']").serialize(),function(res) {
         if (res.warn ==2){
             $('#semiMachiningOrderAddMaterial').hide()
              $("#materialMx tbody").append(res.html);
              resetNumber($("#materialMx"))
         }else{
             msg(res.warn);
         }
        },'json');
    }
    
}

</script>

efo;
        //返回
        return $this->tab($data);
    }

    /**
     * 保存并提交
     * @return bool|string
     */
    public function saveAndCommit(): bool|string
    {
        $resultJson = $this->editEdit();
        $result = json_decode($resultJson,true);
        if ($result['warn'] == 2){
            unset($_SESSION['warn']);
            $resultJson = $this->commitEdit();
        }
        return $resultJson;
    }

    /**
     * 根据BOM计算物料使用量
     */
    public function obtainBom(): bool|string
    {
        $productIdArr = $this->post('productId');
        $sourceIdArr = $this->post('sourceId');
        $materialIdArr = $this->post('skuId');
        $bomIdArr = $this->post('bomId') ?: [];
        $numArr = $this->post('num');
        $unitArr = $this->post('unit');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (static::is_null_array($materialIdArr)) {
            $json['warn'] = '请选择物料';
        } elseif (static::is_null_array($numArr)) {
            $json['warn'] = '您还有物料未填写生产数量';
        } elseif (static::is_null_array($bomIdArr)) {
            $json['warn'] = '您还有物料未选择BOM版本';
        } elseif (static::is_null_array($unitArr)) {
            $json['warn'] = '您还有物料未选择单位';
        } else {
            $machiningOrderClass = new machiningOrderClass();
            $tr[] = ['', '源单编号',  '产品名称', '物料编码', '物料名称', '规格型号', '单位', '额定数量', '损耗率%', '预计用量', '当前可用库存', '备注'];
            foreach ($materialIdArr as $k => $materialId) {
                $bomId = $bomIdArr[$k];
                $num = $numArr[$k];
                $unit = $unitArr[$k];
                $material_list = machiningOrderClass::bomMx($bomId, $materialId, $num, $unit);
                $material_list = $machiningOrderClass->merge_virtual($material_list,[]);
                $material = query('material', "id = '$materialId'");
                if (static::is_null_array($material_list)) {
                    $this->logText(array('type' => self::page, 'text' => "物料【{$material['code']}-{$material['name']}-{$material['model']}】未在BOM中找到所需物料"));
                } else {
                    foreach ($material_list as $key=>$array) {
                        $material = query('material', " id = '$array[materialId]'");
                        $unitOption = machiningOrderClass::unitOption($material['id']);
                        $num =self::formattingFigure($array['quantity'],'numPrecision');
                        $loss = self::formattingFigure(($array['quantity']-$array['num'])/$array['num']*100,'lossRate');
                        $productDemand = query('semi_demands',"id = '$sourceIdArr[$k]'");
                        $machiningOrder = query('machining_order',"id = '$productDemand[sourceId]'");
                        $tr[] = [
                            componentClass::tablePperation($key+1,"delTableRow(this)").
                            hidden(array('name' => 'mxId[]', 'value' => self::getId())) .
                            hidden(array('name' => 'targetSkuId[]', 'value' => $productIdArr[$k])) .
                            hidden(array('name' => 'materialId[]', 'value' => $array['materialId'])),
                            $machiningOrder['orderNo'],
                            materialClass::getName($materialId,short: true),
                            $material['code'],
                            $material['name'],
                            $material['model'],
                            select(array('name' => 'unitDetail[]', 'change' => 'unitChange', 'data' => ['unit' => $material['unit']], 'option' => $unitOption, 'title' => '单位', 'value' => $material['unit'])),
                            text(array('name' => 'mxNum[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100', 'blur' => 'countNum', 'value' => self::formattingFigure($array['num'], 'numPrecision'))),
                            text(array('name' => 'loss[]', 'other' => self::digitalFiltering('lossRate'),'class'=>'text width100', 'blur' => 'countNum', 'value' => $loss)),
                            "<span class='totalNum'>{$num}</span>",
                            "<span class='inventory'>" . machiningOrderClass::inventory($array['materialId'], $material['unit']) . "</span>",
                            text(array('name' => 'mxText[]', 'class' => 'text textPrice')),
                        ];
                    }
                }
            }
            $json['warn'] = 2;
            $json['html'] = $this->tableMany(array('tr' => $tr, 'end' => true));
        }
        return json_encode($json, 320);
    }

    /**
     * 编辑
     *
     * @return bool|string
     */
    public function editEdit(): bool|string
    {
        $id = $this->post('id') ?: self::getId();
        $mxIdArr = $this->post('mxId') ?: [];
        $materialIdArr = $this->post('materialId');
        $numArr = $this->post('mxNum');
        $unitArr = $this->post('unitDetail');
        $mxTextArr = $this->post('mxText');
        $lossArr = $this->post('loss');
        $targetSkuIdArr = $this->post('targetSkuId');

        $productIdArr = $this->post('productId') ?: [];
        $sourceIdArr = $this->post('sourceId');
        $skuIdArr = $this->post('skuId');
        $numMxArr = $this->post('num');
        $batchArr = $this->post('batch');
        $unitMxArr = $this->post('unit');
        $materialTextArr = $this->post('materialText');
        $bomIdArr = $this->post('bomId');
        $routingIdArr = $this->post('routingId');
        $field = [
            'type' =>'生产加工',
            'text' => $this->post('text'),
            'lineId' => $this->post('lineId'),
            'recordDate' => $this->post('recordDate'),
            'startDate' => $this->post('startDate'),
            'endDate' => $this->post('endDate'),
        ];
        $where = " id = '$id' ";
        $info = query(self::table, $where);
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (!empty($info['id']) && $info['state'] == '已确认') {
            $json['warn'] = '此半成品加工单已确认，不能修改';
        } else {
            $this->startTrans();
            if (!$info['id']) {
                $userNo = codeTemplateClass::generateCode(self::page,[
                    'prefix' => 'BCPJG' . date('Ymd',strtotime($field['recordDate'])),
                    'table' => self::table,
                    'field' => 'orderNo',
                    'where' => " and coid = '".self::$coid."'",
                ],$field);
                $field = array_merge($field, [
                    'id' => $id,
                    'orderNo' => $userNo,
                    'orderType'=>'半成品',
                    'state' => '草稿',
                    'coid' => self::$coid,
                    'stid' => $this->control['stid'],
                ]);
                $json['warn'] = static::insert(["table" => self::table, "field" => $field]);
            } else {
                $json['warn'] = static::update([
                    "table" => self::table,
                    "field" => $field,
                    "where" => $where,
                ]);
            }

            //添加或更新明细
            foreach ($mxIdArr as $k => $nid) {
                $mx = query(self::tableMx, "id = '$nid'");
                $lossArr[$k] = $lossArr[$k] ?: 0;
                $numArr[$k] = self::formattingFigure($numArr[$k],'numPrecision');
                if (!empty($mx['id'])) {
                    //更新
                    $warn = static::update([
                        "table" => self::tableMx,
                        "field" => [
                            'materialId' => $materialIdArr[$k],
                            'num' => $numArr[$k],
                            'unit' => $unitArr[$k],
                            'quantity' => self::formattingFigure($numArr[$k] * (1 + $lossArr[$k] / 100), 'numPrecision'),
                            'loss' => floatval($lossArr[$k]) / 100,
                            'text' => $mxTextArr[$k],
                            'targetSkuId' => $targetSkuIdArr[$k],
                        ],
                        "where" => " id = '$nid'",
                    ]);
                } else {
                    //新增
                    $warn = static::insert([
                        "table" => self::tableMx,
                        "field" => [
                            'id' => $nid,
                            'orderId' => $id,
                            'coid' => self::$coid,
                            'materialId' => $materialIdArr[$k],
                            'num' => $numArr[$k],
                            'unit' => $unitArr[$k],
                            'quantity' => self::formattingFigure($numArr[$k] * (1 + $lossArr[$k] / 100), 'numPrecision'),
                            'loss' => floatval($lossArr[$k]) / 100,
                            'text' => $mxTextArr[$k],
                            'targetSkuId' => $targetSkuIdArr[$k],
                        ],
                    ]);
                }
                if (!in_array($warn, ['新增成功', '更新成功'])) {
                    $json['warn'] = $warn;
                    break;
                }
            }

            //添加或更新生产产品明细
            foreach ($productIdArr as $k => $mxId) {
                $mx = query(self::table_material, "id = '$mxId'");
                $sourceTable = '';

                $numMxArr[$k] = self::formattingFigure($numMxArr[$k],'numPrecision');
                if (static::total(array('table' => 'semi_demands', 'where' => "id = '" . $sourceIdArr[$k] . "'")) > 0) {
                    $sourceTable = 'semi_demands';
                }
                if (!empty($mx['id'])) {
                    //更新
                    $warn = static::update([
                        "table" => self::table_material,
                        "field" => [
                            'materialId' => $skuIdArr[$k],
                            'sourceId' => $sourceIdArr[$k],
                            'sourceTable' => $sourceTable,
                            'num' => $numMxArr[$k],
                            'unit' => $unitMxArr[$k],
                            'bomId' => $bomIdArr[$k],
                            'batch'=>$batchArr[$k],
                            'routingId' => $routingIdArr[$k],
                            'text' => $materialTextArr[$k],
                        ],
                        "where" => " id = '$mxId'",
                    ]);
                } else {
                    //新增
                    $warn = static::insert([
                        "table" => self::table_material,
                        "field" => [
                            'id' => $mxId,
                            'orderId' => $id,
                            'coid' => self::$coid,
                            'sourceId' => $sourceIdArr[$k],
                            'sourceTable' => $sourceTable,
                            'materialId' => $skuIdArr[$k],
                            'batch'=>$batchArr[$k],
                            'num' => $numMxArr[$k],
                            'unit' => $unitMxArr[$k],
                            'bomId' => $bomIdArr[$k],
                            'routingId' => $routingIdArr[$k],
                            'text' => $materialTextArr[$k],
                        ],
                    ]);
                }
                if (!in_array($warn, ['新增成功', '更新成功'])) {
                    $json['warn'] = $warn;
                    break;
                }
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                $this->commitTrans();
                delete(array('table' => self::tableMx, 'where' => " id not in ('" . implode("','", $mxIdArr) . "') and orderId = '$id'"));
                delete(array('table' => self::table_material, 'where' => " id not in ('" . implode("','", $productIdArr) . "') and orderId = '$id'"));
                if ($json['warn'] =='新增成功'){
                    self::insertOperateLog($id,self::title,"新建");
                }
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . " id：【" . $id . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
                $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $id;
            } else {
                $this->rollback();
            }
        }

        resp:
        return json_encode($json, 320);
    }


    /**
     * @return bool|string
     */
    public function addMx()
    {
        $materialClassObj = new materialClass();
        $layerId          = $this->get('cla') . ucwords($this->get('fun'));
        $formName         = 'mxForm';
        $notAllowRepeat   = '';
        $data             = [
            'sub'            => " onclick=\"addRow();$('#" . $layerId . "').remove()\" ",
            'continueAdding' => $notAllowRepeat ? " onclick=\"addRow();removeSelectedContent('" . $formName . "')\" " : " onclick=\"addRow();\" ",
            'hidden'         => hidden(["name" => "notAllowRepeat", "value" => $notAllowRepeat]) .
                hidden(array('name' => 'materialId', 'value' => $this->post('materialId') ? implode(',', $this->post('materialId')) : '')),
        ];
        return $materialClassObj->addMx($data);
    }

    /**
     * 编辑
     *
     * @return bool|string
     */
    public function addMxEdit()
    {
        $mxIdArr = $this->post('mxId');
        if (!$this->power(self::page, 'edit')) {
            $json['warn'] = '你还没有编辑权限';
        } elseif (empty($mxIdArr) || !is_array($mxIdArr)) {
            $json['warn'] = '请选择物料';
        } else {
            $tr = [];
            foreach ($mxIdArr as $mxId) {
                $material = query('material', "id = '$mxId'");
                $id = self::getId();
                $unitOption = machiningOrderClass::unitOption($material['id']);
                $unit = select(array(
                    'name' => 'unitDetail[]',
                    'change' => 'unitChange',
                    'data' => ['unit' => $material['unit']],
                    'option' => $unitOption,
                    'value' => $material['unit'],
                    'title' => '单位'
                ));
                $inventoryNum = machiningOrderClass::inventory($material['id'], $material['unit']);
                $tr[] = [
                    componentClass::tablePperation('',"delTableRow(this)").
                    hidden(array('name' => 'mxId[]', 'value' => $id)) .
                    hidden(array('name' => 'materialId[]', 'value' => $mxId)) .
                    hidden(array('name' => 'targetSkuId[]', 'value' => '')),
                    '-',
                    '-',
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    $unit,
                    text(array('name' => 'mxNum[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100','blur' => 'countNum', 'value' => '')),
                    text(array('name' => 'loss[]', 'other' => self::digitalFiltering('lossRate'),'class'=>'text width100','blur' => 'countNum', 'value' => '')),
                    "<span class='totalNum'>0</span>",
                    "<span class='inventory'>{$inventoryNum}</span>",
                    text(array('name' => 'mxText[]', 'class' => 'text textPrice', 'value' => '')),
                ];
            }
            $json['warn'] = 2;
            $json['html'] = $this->tableMany(array('tr' => $tr, 'thead' => false));
        }
        return json_encode($json, 320);
    }


    /**
     *选择生产产品
     *
     * @return bool|string
     */
    public function addMaterial(): bool|string
    {
        $materialClassObj = new materialClass();
        $layerId          = $this->get('cla') . ucwords($this->get('fun'));
        $formName         = 'materialMxForm';
        $notAllowRepeat   = 1;
        $data             = [
            'sub'            => " onclick=\"addMaterial();$('#" . $layerId . "').remove()\" ",
            'continueAdding' => $notAllowRepeat ? " onclick=\"addMaterial();removeSelectedContent('" . $formName . "')\" " : " onclick=\"addMaterial();\" ",
            'hidden'         => hidden(["name" => "notAllowRepeat", "value" => $notAllowRepeat]) .
                hidden(["name" => "supplyControl", "value" => '允许生产']) .
                hidden(["name" => "formName", "value" => $formName]) .
                hidden(array('name' => 'materialId', 'value' => $this->post('skuId') ? implode(',', $this->post('skuId')) : '')),
        ];
        return $materialClassObj->addMx($data);
    }

    /**
     * 编辑
     *
     * @return bool|string
     */
    public function addMaterialEdit(): bool|string
    {
        $materialIdArr = $this->post('mxId');
        if (!$this->power(self::page, 'edit')) {
            $json['warn'] = '你还没有编辑权限';
        } elseif (static::is_null_array($materialIdArr)) {
            $json['warn'] = '请选择物料';
        } else {
            $tr = [];
            $machinngObj = new machiningOrderClass();
            foreach ($materialIdArr as $materialId) {
                $material = query('material', "id = '$materialId'");
                $unitOption = machiningOrderClass::unitOption($material['id']);
                //默认bom
                $detaultBom = query('bom', "materialId = '$material[id]' and state = '启用' and isDefault = 1");
                //默认工艺路线
                $routingId = $machinngObj->defaultRouting($material['id']);
                $detaultRouting = query('routing', "id = '$routingId'");
                $allTypeId = explode('/',$material['typePath']);
                $id = self::getId();
                $unit = select(array('name' => 'unit[]', 'change' => 'unitChangeProduct', 'data' => ['unit' => $material['unit']], 'option' => $unitOption, 'value' => $material['unit'], 'title' => '单位'));
                $bom = selectMultiple(array('name' => 'bomId[]', 'class' => 'width200', 'title' => 'BOM版本', 'table' => 'bom', 'where' => "bomType like '%生产%' and state = '启用' and coid = '" . self::$coid . "' and materialId = '$material[id]' order by time desc", 'sqlId' => 'id', 'sqlField' => 'bomVersion', 'value' => $detaultBom['id']));
                $routing = selectMultiple(array('name' => 'routingId[]', 'class' => 'width200', 'title' => '工艺路线',  'option' => $machinngObj->routingOption($material['id'], $allTypeId),'value' => $detaultRouting['id']));

                $tr[] = [
                    componentClass::tablePperation('',"delTableRow(this)").
                    hidden(array('name' => 'productId[]', 'value' => $id)) .
                    hidden(array('name' => 'skuId[]', 'value' => $material['id'])) .
                    hidden(array('name' => 'sourceId[]', 'value' => '')),
                    '-',
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    $unit,
                    text(array('name' => 'num[]', 'other' => self::digitalFiltering('numPrecision'),'class'=>'width100', 'value' => '')),
                    text(array('name' => 'batch[]', 'class' => 'width100','value' => '')),
                    $bom,
                    $routing,
                    text(array('name' => 'materialText[]', 'class' => 'width100', 'value' => '')),
                ];
            }
            $json['warn'] = 2;
            $json['html'] = $this->tableMany(['tr' => $tr, 'thead' => false]);
        }
        return json_encode($json, 320);
    }

    /**
     * 启用/停用
     */
    public function stateSwitch(): bool|string
    {
        $isClose = $this->post('type');
        //生成表单
        $html = $this->layerEdit(array(
            "table" => array(
                array(
                    "提示：" => "是否确认" . ($isClose == 1 ? '关闭' : '开启') . "此订单？",
                ),
            ), 'hidden' => hidden(array('name' => 'type', 'value' => $isClose)),
        ));
        //返回
        return $this->layer(array("title" => "订单状态", "height" => 165, "html" => $html, 'formTwo' => 'listForm'));
    }

    /**
     * 启用/停用
     */
    public function stateSwitchEdit(): bool|string
    {
        $idArr = $this->post('id') ? [$this->post('id')] : $this->post('listId');
        $isClose = $this->post('type');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有" . self::title . "的编辑权限";
        } elseif (empty($idArr) || !is_array($idArr)) {
            $json['warn'] = "请选择数据";
        } else {
            $field = [
                'isClose' => $isClose,
            ];
            $json['warn'] = update(array('table' => self::table, 'field' => $field, 'where' => " id in ('" . implode("','", $idArr) . "')"));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                $type = $isClose == 1 ? '关闭' : '开启';
                foreach ($idArr as $id) {
                    self::insertOperateLog($id,self::title,$type);
                }
                //添加日志
                $text = $this->control['name'] . $type . "了" . self::title . "， id：【" . implode(",", $idArr) . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $type . '成功';
                $json['warn'] = 2;
            }
        }
        //返回
        return json_encode($json, 320);
    }


    /*详情页*/
    public function detail(): string
    {
        $info = query(self::table, " id = '{$this->get('id')}'");
        if (empty($info['id'])) {
            $html = '未找到此' . self::title;
        } else {
            //菜单
            $data = array(
                "id" => $info['id'],
                'menu'=>[
                    'detail'=>'基本信息',
                    'materialTrack'=>'物料追溯',
                    'qualityTrack'=>'质量追溯',
                ]
            );

            $button = [];
            if ($this->power(self::page, "confirm") && $info['state'] == '待确认') {
                $button[] = [
                    "name" => "复核",
                    "type" => "弹出层",
                    "cla" => $this->get('cla'),
                    "fun" => "operate",
                    "post" => ["act" => 'confirm', "id" => $info['id']],
                    'style' => 'li-btn-blue-bg',
                ];
            }
            if ($this->power(self::page, "confirm") && $info['state'] != '草稿' && !$info['isClose']) {
                $button[] = [
                    "name" => "撤回",
                    "type" => "弹出层",
                    "cla" => $this->get('cla'),
                    "fun" => "operate",
                    "post" => ["act" => 'cancel', "id" => $info['id']],
                ];
            }
            if ($info['state'] == '草稿') {
                if ($this->power(self::page, "edit")) {
                    //按钮
                    $button[] = [
                        "name" => "提交",
                        "type" => "弹出层",
                        "cla" => $this->get('cla'),
                        "fun" => "operate",
                        "post" => ["act" => 'commit', "id" => $info['id']],
                        'style' => 'li-btn-blue-bg',
                    ];
                    //按钮
                    $button[] = [
                        "name" => "编辑",
                        "type" => "顶部页卡",
                        "title" => "编辑用户",
                        "url" => $this->root . "control/adIndex.html?cla={$this->get('cla')}&fun=edit&id=" . $info['id'],

                    ];
                }
                if ($this->power(self::page, "del")) {
                    //按钮
                    $button[] = [
                        "name" => "删除",
                        "type" => "弹出层",
                        "cla" => $this->get('cla'),
                        "fun" => "operate",
                        "post" => ["act" => 'del', "id" => $info['id']],
                    ];
                }
            }
            //按钮
            $button[] = [
                "name" => "打印",
                "type" => "点击事件",
                "fun" => "window.open('" . root . "control/adIndex.html?cla=" . self::page . "&fun=printPage&id={$info['id']}')",
            ];

            if ($this->power(self::page, "edit") && $info['state'] == '已确认') {
                //按钮
                $isClose = $info['isClose'] == 1 ? 0 : 1;
                $name = $info['isClose'] == 1 ? '开启' : '关闭';
                $button[] = [
                    "name" => $name,
                    "type" => "点击事件",
                    "fun" => "layer('" . self::page . "','stateSwitch',{id:'" . $info['id'] . "',type:'{$isClose}'})",
                ];
            }
            $button[] = [
                "name" => "单据追踪",
                "type" => "顶部页卡",
                "title" => "单据追踪",
                "url" => $this->root . "control/adIndex.html?cla=orderTrack&fun=home&orderType=半成品加工单&id=" . $info['id'],
            ];
            //操作记录
            $button[] = self::operateLogBut($info['id'],1);

            $tr[] = ['源单编号','产品名称', '物料编码', '物料名称', '规格型号', '单位', '额定数量', '损耗率%', '预计用量', '当前可用库存', '备注'];
            $result = find(array('table' => self::tableMx, 'where' => "orderId = '$info[id]' order by list"));
            $total = ['num'=>0,'quantity'=>0,'inventory'=>0];
            foreach ($result['array'] as $array) {
                $material = query('material', " id = '$array[materialId]'");
                $inventoryNum = machiningOrderClass::inventory($array['materialId'], $array['unit']);
                $table_material = query(self::table_material, " id = '$array[targetSkuId]'");
                $productDemand = query('semi_demands',"id = '$table_material[sourceId]'");
                $machining_order = query('machining_order', "id = '$productDemand[sourceId]'");
                $tr[] = [
                    $machining_order['orderNo'],
                    materialClass::getName($table_material['materialId'],short: true),
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    $array['unit'],
                    self::lostZero($array['num'],'numPrecision'),
                    ($array['loss'] * 100) . '%',
                    self::lostZero($array['quantity'],'numPrecision'),
                    $inventoryNum,
                    $array['text'],
                ];
                $total['num'] += $array['num'];
                $total['quantity'] += $array['quantity'];
                $total['inventory'] += $inventoryNum;
            }
            $total_tr = [
                6 => self::lostZero($total['num'], 'numPrecision'),
                8 => self::lostZero($total['quantity'], 'numPrecision'),
                9 => self::lostZero($total['inventory'], 'numPrecision'),
            ];

            $materialTr[] = ['关联生产计划', '产品编码', '产品名称', '规格型号', '单位', '计划数量', '生产批次', 'BOM版本', '工艺路线', '备注'];
            $result = find(array('table' => self::table_material, 'where' => "orderId = '$info[id]' order by list"));
            foreach ($result['array'] as $array) {
                $material = query('material', " id = '$array[materialId]'");
                $relativeNo = '-';
                if ($array['sourceTable'] == 'semi_demands') {
                    $productDemand = query('semi_demands',"id = '$array[sourceId]'");
                    $machiningOrder = query('machining_order', "id = '$productDemand[sourceId]'");
                    $relativeNo = $machiningOrder['orderNo'];
                }
                $bom = query('bom', "id = '$array[bomId]'");
                $routing = query('routing', "id = '$array[routingId]'");
                $materialTr[] = [
                    $relativeNo,
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    $array['unit'],
                    self::lostZero($array['num'],'numPrecision'),
                    $array['batch'],
                    $bom['bomVersion'],
                    $routing['description'],
                    $array['text'],
                ];
            }
            $line = query('product_line', "id = '$info[lineId]'");
            //生成表单
            $data['button'] = $this->tableShowButton($button);
            $data['html'] = $this->tableShow(array(
                "基本信息" => array(
                    array(
                        "生产线" => $line['workshop'] . '-' . $line['name'],
                        "计划开工日期" => $info['startDate'],
                        "计划完工日期" => $info['endDate'],
                        "单据编号" => $info['orderNo'],
                    ),
                    array(
                        "制单人" => self::findStaff($info['stid']),
                        "状态" => $info['state']
                    ),
                    array(
                        "备注" => pre($info['text']),
                    ),
                ),
            ));
            $data['html'] .= $this->detailList([
                'title' => '产品明细',
                'html' => $this->listTable(array(
                    'tr' => $materialTr,
                    'showSort' => true,
                    'total' => [5=>self::lostZero(array_sum(array_column((array)$result['array'],'num')),'num')]
                )),
            ]);
            $data['html'] .= $this->detailList([
                'title' => '所需物料',
                'html' => $this->listTable(array('tr' => $tr, 'showSort' => true, 'total' => $total_tr)),
            ]);
            //生成页面
            $html = $this->tab($data);
        }
        //返回
        return $html;
    }

    /**
     * 确认
     */
    public function confirmEdit()
    {
        $id = $this->post('id');
        $info = query(self::table, " id = '$id'");
        $field = [
            'state' => '已确认',
            'checkId' => self::$stid,
            'confirmTime' => $this->time,
        ];
        if (!$this->power(self::page, 'confirm')) {
            $json['warn'] = '你还没有确认权限';
        } elseif (empty($info['id'])) {
            $json['warn'] = '未找到此半成品加工单';
        } elseif ($info['state'] != '待确认') {
            $json['warn'] = '此半成品加工单不是待确认状态，不能确认';
        } else {
            $machiningOrder = new machiningOrderClass();
            $this->startTrans();
            $json['warn'] = update(array(
                "table" => self::table,
                "field" => $field,
                "where" => "id = '$info[id]'",
            ));
            if (optionSettingClass::getSettingItem('生产','autoNewSendOrder') && optionSettingClass::getSettingItem('生产','productCtrlMethod') =='machiningSendOrder'){
                //生成派工单
                $bool = $this->creatSendOrder($id);
                if ($bool !== true) {
                    $json['warn'] = $bool;
                }
            }elseif(optionSettingClass::getSettingItem('生产','productCtrlMethod') =='productCard'){
                //生成生产流转卡
                $obj = new machiningOrderClass();
                $bool = $obj->creatCard($id,'半成品加工单',self::page);
                if ($bool !== true) {
                    $json['warn'] = $bool;
                }
            }

            //生成配料需求
            $bool = $machiningOrder->ingredientsDemands($id);
            if ($bool !== true) {
                $json['warn'] = $bool;
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                $this->commitTrans();
                // 单据是否需要复核
                if(!in_array(self::page,self::$publicSettings['documentReview'])) {
                    self::insertOperateLog($info['id'],self::title,"提交、复核");
                }else{
                    self::insertOperateLog($info['id'],self::title,"复核");
                }
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
                $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $info['id'];
            }else{
                $this->rollback();
            }
        }
        resp:
        return json_encode($json, 320);
    }
    /**
     * 生成派工单
     */
    public function creatSendOrder($id): bool|string
    {
        $info = query(self::table, " id = '$id'");
        $all = find(array('table' => self::table_material, "where" => "orderId = '$id' order by list asc"));
        foreach ($all['array'] as $array) {
            $routingDetail = find(array('table' => 'routing_detail', 'where' => "orderId = '$array[routingId]' order by list asc"));
            foreach ($routingDetail['array'] as $val) {
                $material = query('material', " id = '$array[materialId]'");
                $field = [
                    'id' => self::getId(),
                    'coid' => self::$coid,
                    'orderType'=>'半成品',
                    'classify'=>$val['isOut']=='是'?'委外派工':'生产派工',
                    'recordDate'=>$this->date,
                    'type' => $info['type'],
                    'lineId' => $info['lineId'],
                    'routingId'=>$array['routingId'],
                    'routingMxId'=>$val['id'],
                    'machiningOrderId' => $info['id'],
                    'machiningOrderMxId' => $array['id'],
                    'materialId' => $array['materialId'],
                    'unit' => $array['unit'],
                    'num' => $array['num'],
                    'processId' => $val['processId'],
                    'startDate' => $info['startDate'],
                    'endDate' => $info['endDate'],
                    'state' => '草稿',
                    'stid' => self::$stid,
                ];
                $userNo = codeTemplateClass::generateCode('machiningSendOrder',[
                    'prefix' => 'SCPG' . date('Ymd'),
                    'table' => 'machining_send_order',
                    'field' => 'orderNo',
                    'where' => " and coid = '".self::$coid."'",
                ],$field);
                $field['orderNo'] = $userNo;
                $warn = static::insert(array(
                    'table' => 'machining_send_order',
                    'field' => $field,
                ));
                if ($warn != '新增成功') {
                    return "产品【{$material['code']}-{$material['name']}-{$material['model']}】生成派工单失败";
                }
            }
        }
        return true;
    }

    /**
     * 撤回
     */
    public function cancelEdit()
    {
        $id = $this->post('id');
        $info = query(self::table, " id = '$id'");
        $field = [
            'state' => '草稿',
            'checkId' => '',
            'confirmTime' => '',
        ];
        if (!$this->power(self::page, 'cancel')) {
            $json['warn'] = '你还没有撤回权限';
        } elseif (empty($info['id'])) {
            $json['warn'] = '未找到此半成品加工单';
        } elseif ($info['state'] != '已确认') {
            $json['warn'] = '此半成品加工单不是已确认状态，无需撤回';
        } elseif (static::total(array('table' => 'pick_order_detail', "where" => "sourceId in (select id from machining_order_detail where orderId = '$info[id]')  and coid = '" . self::$coid . "'")) > 0) {
            $json['warn'] = '已有领料单或退料单关联此半成品加工单，不能撤回';
        } elseif (static::total(array('table' => 'machining_in_order_detail', "where" => "sourceId in (select id from machining_order_mx where orderId = '$info[id]')  and coid = '" . self::$coid . "'")) > 0) {
            $json['warn'] = '已有生产入库单关联此半成品加工单，不能撤回';//生产入库单
        } elseif (static::total(array('table' => 'machining_send_order', "where" => "machiningOrderId= '$info[id]' and classify = '生产派工' and coid = '" . self::$coid . "'")) > 0) {
            $json['warn'] = '已有生产派工单关联此生产计划，不能撤回';
        } elseif (static::total(array('table' => 'machining_send_order', "where" => "machiningOrderId= '$info[id]' and classify = '委外派工'  and coid = '" . self::$coid . "'")) > 0) {
            $json['warn'] = '已有委外派工单关联此生产计划，不能撤回';
        } elseif (static::total(array('table' => 'process_report', "where" => "machiningOrderId= '$info[id]' and sourceTable = 'machining_card_detail'  and coid = '" . self::$coid . "'")) > 0) {
            $json['warn'] = '已有生产流转卡关联此单据，不能撤回';
        }  else {
            $json['warn'] = update(array(
                "table" => self::table,
                "field" => $field,
                "where" => "id = '$info[id]'",
            ));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                delete(array('table' => 'ingredients_demands', 'where' => "machiningOrderId = '$info[id]'"));
                delete(array('table' => 'machining_card_detail', 'where' => "orderId in (select id from machining_card where sourceId = '$info[id]')"));
                delete(array('table' => 'machining_card', 'where' => "sourceId = '$info[id]'"));
                self::insertOperateLog($info['id'],self::title,"撤回");
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
                $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $info['id'];
            }
        }
        resp:
        return json_encode($json, 320);
    }
    /**
     * Desc : 提交前数据验证
     * User : you name
     * Date : 2023-11-17 16:04
     * @param $info
     * @return string|bool
     */
    public function dataValidation($info): string|bool
    {
        $annotation = [
            'type' => '加工单类型',
            'lineId' => '生产线',
            'recordDate' => '单据日期',
            'startDate' => '计划开工日期',
            'endDate' => '计划完工日期',
        ];
        $rules = [
            'type' => 'required',
            'lineId' => 'required',
            'recordDate' => 'required|date',
            'startDate' => 'required|date',
            'endDate' =>  'required|date',
        ];
        // 校验是否符合规则
        $vt = new \verify();
        $result = $vt->setAliases($annotation)->validate($info, $rules)->isOk();
        if ($result === false) {
            return $vt->getErrs()[0];  // 多个规则提示最前面一条
        }
        if (strtotime($info['endDate']) < strtotime($info['startDate'])) {
            return '半成品加工单开工时间不能小于完工时间';
        }
        $result = find(array('table' => self::table_material, 'field' => 'id,materialId,num,unit,routingId', 'where' => "orderId = '$info[id]' order by list"));
        if(count($result['array']) == 0){
            return "请选择需要生产的产品";
        }
        if(static::is_null_array(array_column($result['array'],'num'),false)){
            return "产品明细中【计划数量】不能为空，且必须大于0";
        }
        if(static::is_null_array(array_column($result['array'],'unit'))){
            return "产品明细中【单位】不能为空";
        }
        if(static::is_null_array(array_column($result['array'],'routingId'))){
            return "产品明细中【工艺路线】不能为空";
        }
        $withOutMaterial = optionSettingClass::getSettingItem('生产','withOutMaterial');
        $result = find(array('table' => self::tableMx, 'field' => 'id,materialId,num,unit', 'where' => "orderId = '$info[id]' order by list"));
        if(!$withOutMaterial && count($result['array']) == 0){
            return "未找到所需物料";
        }
        if(!$withOutMaterial && static::is_null_array(array_column($result['array'],'materialId'))){
            return "所需物料中【属性】不能为空";
        }
        if(!$withOutMaterial && static::is_null_array(array_column($result['array'],'unit'))){
            return "所需物料中【单位】不能为空";
        }
        if(!$withOutMaterial && static::is_null_array(array_column($result['array'],'num'),false)){
            return "所需物料中【额定数量】不能为空，且必须大于0";
        }

        return true;
    }
    /**
     * 提交
     */
    public function commitEdit()
    {
        $id = $this->post('id');
        $info = query(self::table, " id = '$id'");
        $field = [
            'state' => '待确认',
        ];
        //提交前数据验证
        $json['warn'] = $this->dataValidation($info);
        if($json['warn'] !== true){
            goto resp;
        }
        if (!$this->power(self::page, 'edit')) {
            $json['warn'] = '你还没有编辑权限';
        } elseif (empty($info['id'])) {
            $json['warn'] = '未找到此半成品加工单';
        } elseif ($info['state'] != '草稿') {
            $json['warn'] = '此半成品加工单不是草稿状态，不能提交';
        } else {
            $this->startTrans();
            $json['warn'] = update(array(
                "table" => self::table,
                "field" => $field,
                "where" => "id = '$info[id]'",
            ));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                // 单据是否需要复核
                if(!in_array(self::page,self::$publicSettings['documentReview'])){
                    $resultJson = $this->confirmEdit();
                    $json = json_decode($resultJson,true);
                    if ($json['warn'] != 2){
                        $this->rollback();
                        goto resp;
                    }
                }else {
                    self::insertOperateLog($info['id'],self::title,"提交");
                }
                $this->commitTrans();
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
                $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $info['id'];
            } else {
                $this->rollback();
            }
        }
        resp:
        return json_encode($json, 320);
    }

    // 操作中转
    public function operate()
    {
        $act = $this->post('act') ?? '';
        $pwd = $word = false; // 需要密码
        $form = $power = '';
        switch ($act) {
            case 'batchDel':
                $act = 'del';
                $msg = '删除' . self::title;
                $title = self::page . 'Delete';
                $function = 'batchDel';
                $form = self::page . 'OperateForm, listForm, quoForm';
                $power = '';
                break;
            case 'confirm':
                $act = 'confirm';
                $msg = '确认';
                $title = '是否已确认此半成品加工单，确认后将不可修改？';
                $function = 'confirmEdit';
                $form = self::page . 'OperateForm, detailForm';
                $power = '';
                $word = true;
                break;
            case 'commit':
                $act = 'edit';
                $msg = '编辑';
                $title = '是否确认提交此半成品加工单？';
                $function = 'commitEdit';
                $form = self::page . 'OperateForm, detailForm';
                $power = '';
                $word = true;
                break;
            case 'cancel':
                $act = 'cancel';
                $msg = '撤回';
                $title = '是否确认撤回此半成品加工单？';
                $function = 'cancelEdit';
                $form = self::page . 'OperateForm, detailForm';
                $power = '';
                $word = true;
                break;
            case 'close':
                $act = 'edit';
                $msg = '关闭';
                $title = '是否确认批量关闭选中的半成品加工单？';
                $function = 'closeEdit';
                $form = self::page . 'OperateForm, listForm, quoForm';
                $power = '';
                $word = true;
                break;
            default:
                $act = 'del';
                $msg = '删除' . self::title;
                $title = self::page . 'Delete';
                $function = 'delete';
                $form = self::page . 'OperateForm, listForm, quoForm';
                $power = '';
                break;
        }
        if (!$this->power(self::page, $act)) {
            $_SESSION['warn'] = '你还没有' . $msg . '的权限';
            $json = [
                'warn' => 2,
                'href' => root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=home',
            ];
        } else {
            return $this->confirm([
                'title' => $title,
                'function' => $function,
                'form' => $form,
                'power' => $power,
                'pwd' => $pwd,
                'word' => $word,
            ]);
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 删除
     *
     * @return bool|string
     */
    public function delete()
    {
        $array = $this->post('listId') ?? $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = "你没有删除的权限";
        } elseif (empty($array)) {
            $json['warn'] = "你一个数据都没有选择呢";
        } else {
            $text = "";
            $x = 0;
            $array = is_array($array) ? $array : [$array];
            foreach ($array as $id) {
                $info = query(self::table, " id = '$id' ");
                if ($info['state'] == '已确认') {
                    $warn = "删除失败：已确认，暂不能删除";
                } else {
                    //最后删除基本参数
                    delete(array("table" => self::table, "where" => " id = '$id' "));
                    delete(array("table" => self::tableMx, "where" => " orderId = '$id' "));
                    delete(array("table" => self::table_material, "where" => " orderId = '$id' "));
                    delete(array("table" => "auditing_follow", "where" => " typeId = '$id' "));
                    //返回
                    $warn = "删除成功";
                    $x++;
                }
                $text .= self::title . "ID【" . $info['id'] . "】" . $warn . "。<br>";
            }
            //添加日志
            $text = $this->control['name'] . "删除了" . self::title . "，结果如下：<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] = "删除了" . $x . "个" . self::title . "，详情见系统日志。";
            $json['warn'] = 2;
            $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }
        return json_encode($json, 320);
    }

	/**
	 * 批量打印
	 *
	 * @return string
	 */
	public function batchPrint(): string
	{
		$lists = $this->get('lists');
		if(empty($lists)){
			exit('参数错误');
		}else{
			$listId = base64_decode($lists, true);
			$array = explode(',', $listId);
			$data = [];
			foreach ($array as $id){
				$data[] = static::printPage($id, false);
			}
			return (new printTemplateClass())->start(self::page, $data);
		}
	}

	/**
	 * 打印
	 *
	 * @return string
	 */
	public function printPage($param = '', $isReturn = true): string|array
	{
		$id                  = $param ?: $this->get('id');
		$info                = query(self::table, " id = '$id'");
        $line = query('product_line', "id = '$info[lineId]'");
        $info['companyName'] = query('company', "coid = '" . self::$coid . "'")['name']; //公司名称//公司名称
        $info['title']       = self::title;
        $info['lineName']       = $line['workshop'].$line['name'];
        $info['materialName'] = '产品明细';
        $info['printTime']   = $this->time;
        $info['stid']        = self::findStaff($info['stid']);
        $info['qr']          = "source=" . self::table . "&id=" . $info['id'];
        $info['tags'] = orderTagClass::getTagName($info['id']);
        $detail              = find(['table' => self::table_material, 'where' => "orderId = '$info[id]' order by list asc"])['array'];
        $items               = [];
        $x                   = 1;
        $totalNum            = 0;
        foreach ($detail as $array) {
            $material    = query('material', "id = '$array[materialId]'");
            $relativeNo = '-';
            if ($array['sourceTable'] == 'semi_demands') {
                $productDemand = query('semi_demands',"id = '$array[sourceId]'");
                $machiningOrder = query('machining_order', "id = '$productDemand[sourceId]'");
                $relativeNo = $machiningOrder['orderNo'];
            }
            $items[]     = [
                'no'              => $x,
                'relativeNo'=>$relativeNo,
                'materialCode'    => $material['code'],
                'materialName'    => $material['name'],
                'model'           => $material['model'],
                'unit'            => $array['unit'],
                'text'             => $array['text'],
                'num'             => self::lostZero($array['num'],'numPrecision'),
            ];
            $x++;
            $totalNum += $array['num'];
        }
        $append         = [
            'no'  => '合计',
            'num' => $totalNum,
        ];
        $items[]        = $append;
        $info['detail'] = $items;
	    if ($isReturn) {
		    return (new printTemplateClass())->start(self::page, $info);
	    } else {
		    return $info;
	    }
    }

    /*列表页-查询条件*/
    public function qualityTrackOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    "状态" => checkbox(array('name' => 'state', 'value' => ['待质检', '已质检'], 'checked' => ['待质检'])),
                ],
                [
                    "单据编号" => text(array("name" => "orderNo")),
                    "生产线"   => selectMultiple(["name" => "lineId", 'table' => "product_line", 'sqlId' => 'id', 'where' => "coid = '" . self::$coid . "'", 'sqlField' => 'name', 'class' => 'width200']),
                    '物料编码' => text(array("name" => "code")),
                ],
                [
                    '物料名称' => text(array("name" => "materialName")),
                    '不良原因' => text(array("name" => "reason")),
                    '处置方式'  => repeatSelect(array('name' => 'method', 'sqlForm' => " quarantine_reason where coid = '" . self::$coid . "'", 'sqlField' => 'method')),
                ],
                [
                    "质检日期" => text(array("name" => "createTime", 'laydate' => ['type' => 'date', 'range' => '~'])).
                        hidden(array('name' => 'id', 'value' => $this->get('id'))),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    public function qualityTrack(){
        $html = $this->qualityTrackOptions(false);
        //控件
        $button = "";
        $json['html'] = $this->search($html, layout: 'pop', toolButton: $button);
        return json_encode($json, 320);
    }
    public function qualityTrackSearch(){
        $id = $this->post('id');
        $equal = [
            "a.targetId" => $this->post('lineId'),
            'a.coid' => self::$coid,
        ];
        $like = [
            "a.orderNo" => $this->post('orderNo'),
            "b.code" => $this->post('code'),
            "b.materialName" => $this->post('materialName'),
        ];
        $and = " and a.type in (2,4) and (sourceMxId in (select id from machining_in_order_detail where sourceId in (select id from machining_order_mx where orderId = '$id'))
         or sourceId in (select id from process_report where sendId in (select id from machining_send_order where machiningOrderId = '$id')))";
        //生成查询语句
        $where   = search([
                "="    => $equal,
                "like" => $like,
            ]).$and;
        //排序
        $orderBy = $this->listSort(array(
            "search" => $this->post('list_sort_key') ?: '"list asc,`time`',
            "sort"   => $this->post('list_sort') ?: "desc",
            "array"  => array(),
        ));
        $page = $this->page([
            "table" => 'quality_order as a join material as b on a.materialId = b.id',
            "where" => $where,
            'field' => "a.*,b.name,b.code,b.model",
            "order" => $orderBy['orderBy']
        ]);
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array("");
        $url = root.'control/adIndex.html?cla=';
        foreach ($page['array'] as $array) {
            $cla = $array['type']==2?'processInspection':'processingInspection';
            $dominate  = [
                "box" => [
                    "name" => "id",
                    "value" => $array['id']
                ],
                'edit' => ["title" => "编辑", "click" => "newIframe('" . self::title . "详情','" . $url . $cla."&fun=detail&id=" . $array['id'] . "')"],
            ];
            $sourceInfo = [];
            $processName='';
            if ($array['type'] ==2){
                $sourceInfo = query('machining_in_order',"id = '$array[sourceId]'");
            }elseif($array['type'] ==4){
                $sourceInfo = query('process_report',"id = '$array[sourceId]'");
                $sourceInfo['recordDate'] = $sourceInfo['teamNo'];
                $process = query('process',"id = '$sourceInfo[processId]'");
                $processName = $process['name'];
            }
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case "type":
                        $type = $array['type'] ==2?'制终检验':'制程检验';
                        $row[] = $type;
                        break;
                    case "recordDate":
                    case "orderNo":
                        $row[] = $sourceInfo[$key];
                        break;
                    case "lineName":
                        $line = query('product_line', "id = '$array[targetId]'");
                        $lineName = $line['workshop'] . '-' . $line['name'];
                        $row[] = $lineName;
                        break;
                    case "processName":
                        $row[] = $processName;
                        break;
                    case "num":
                    case "passNum":
                        $row[] = self::lostZero($array[$key], 'numPrecision');
                        break;
                    case "badNum":
                        $row[] = $array['num']-$array['passNum'];
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //控件
        //生成页面
        $li = $this->li(array(
            "body"        => $body,
            "install"     => $installSearch,
            "button"      => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page"        => $page['para'],
        ));
        $json['html'] = $page['hint'] . $li . $page['button'];
        return json_encode($json, 320);
    }


    /**
     * 物料追溯
     * @return false|string
     */
    public function materialTrack(){
        $machiningOrderObj = new machiningOrderClass();
        $bomArray = $machiningOrderObj->getFactMaterialNum($this->get('id'));
        $tr[] = array('存货类别',"物料编码","物料名称","规格型号","单位",'额定数量',"损耗率(%)",'计划用量','实际BOM用量','实际领料量','实际退料量','实际用量','备注');
        $sql = find(array("table" => "machining_order_detail","where" => "orderId = '".$this->get('id')."' order by list asc "));
        foreach($sql['array'] as $array){
            $material = query('material',"id = '$array[materialId]'");
            //领料

            $pickNum=0;
            $pickOrderAll = find(array(
                'table'=>'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                "where"=>"a.state = '已确认' and a.type=0 and b.sourceId = '$array[id]' and b.materialId = '$array[materialId]'"
            ));
            foreach ($pickOrderAll['array'] as $val){
                $pickNum+=machiningOrderClass::material_num_change($array['materialId'],$val['unit'],$array['unit'],$val['num']);
            }
            $pickNum = round($pickNum,2);
            //退料
            $refundNum=0;
            $refundOrderAll = find(array(
                'table'=>'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                "where"=>"a.state = '已确认' and a.type=1 and b.sourceId = '$array[id]' and b.materialId = '$array[materialId]'"
            ));
            foreach ($refundOrderAll['array'] as $val){
                $refundNum+=machiningOrderClass::material_num_change($array['materialId'],$val['unit'],$array['unit'],$val['num']);
            }
            $refundOrderAll = find(array(
                'table'=>'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                "where"=>"a.state = '已确认' and a.type=1 and b.sourceId in (select id from pick_order_detail where sourceId = '$array[id]') and b.materialId = '$array[materialId]'"
            ));
            foreach ($refundOrderAll['array'] as $val){
                $refundNum+=machiningOrderClass::material_num_change($array['materialId'],$val['unit'],$array['unit'],$val['num']);
            }
            $refundNum = round($refundNum,2);

            $bomNum = 0;//实际BOM用量
            $mxAll = find(array('table'=>'machining_order_mx','where'=>"orderId = '".$this->get('id')."'"));
            foreach ($mxAll['array'] as $item){
                $bomNum+=$machiningOrderObj->getMaterialBom($bomArray,$item['id'],$array['materialId']);
            }

            $tr[] = array(
                $material['subject'],
                $material['code'],
                $material['name'],
                $material['model'],
                $array['unit'],
                self::lostZero($array['num'],'numPrecision'),
                ($array['loss']*100).'%',
                self::lostZero($array['quantity'],'numPrecision'),
                $bomNum,
                $pickNum,
                $refundNum,
                $pickNum-$refundNum,
                $array['text']
            );
        }

        //材料分配明细
        $disTr[] = ['存货类别','物料编码', '物料名称', '规格型号', '单位',  '实际BOM用量', '实际分配用量'];
        $all = find(array('table'=>'material_distribute_num','where'=>"machiningOrderId = '".$this->get('id')."' and num >0 order by list"));
        foreach ($all['array'] as $array){
            $material = query('material', " id = '$array[materialId]'");
            $disTr[] = [
                $material['subject'],
                $material['code'],
                $material['name'],
                $material['model'],
                $array['unit'],
                $machiningOrderObj->getMaterialBom($bomArray,$array['machiningOrderMxId'],$array['materialId']),
                self::lostZero($array['num'],'numPrecision')
            ];
        }
        //构建表单
        $json['html'] = "
            <div class='tab-content'>
                " .
                $this->detailList([
                    'title' => '领料明细',
                    'html' => $this->listTable(array("tr" => $tr, 'showSort' => true)),
                ]).
                $this->detailList([
                    'title' => '材料分配明细',
                    'html' => $this->listTable(array("tr" => $disTr, 'showSort' => true)),
                ]).
                "
            </div>";
        //返回
        return json_encode($json,320);
    }



}
